#include "LRU_Stack.h"
#include <algorithm>

LRU_Stack::LRU_Stack(void)
{
}

LRU_Stack::LRU_Stack( int pw, int rep, int size )
{
	cache_size = size;
	m_power_aware_mode = pw;
	m_cache_replace_mode = rep;
}


LRU_Stack::~LRU_Stack(void)
{
}

int LRU_Stack::accessBlock( int block_addr, int mode )
{
	if(block_addr < 0)
		return -1;
	if(m_power_aware_mode == 0)
		mode = 0; //regular
	bool is_bloack_find =findBloack(block_addr, mode);
	if(!is_bloack_find){
		updateBloack(block_addr, mode);
		return block_addr;
	}
	return -1;
}

bool LRU_Stack::findBloack( int block_adde, int mode )
{
	std::list<int>* target_cache;
	if(mode ==1 )
	{
		target_cache = &m_cahce_priority;
	}
	else
		target_cache = &m_cahce_regular;

	std::list<int>::iterator lit = std::find(target_cache->begin(), target_cache->end(), block_adde);
	if(lit == target_cache->end())
		return false;
	else{
		//update the order of the cache 
		target_cache->remove(block_adde);
		target_cache->push_front(block_adde);
		return true;
	}
}

void LRU_Stack::updateBloack( int block_adde, int mode )
{
	std::list<int>* target_cache;
	if(mode == 1 && m_cahce_regular.size() == 0)
		target_cache = &m_cahce_priority;
	else
		target_cache = &m_cahce_regular;

	if(m_cahce_priority.size() + m_cahce_regular.size() >= cache_size)
	{
		if(m_cache_replace_mode ==0){
			target_cache->pop_back(); //LRU
			//target_cache->push_front(block_adde);
		}
		if(m_cache_replace_mode == 1){
			target_cache->pop_front(); //MRU
			//target_cache->push_back(block_adde);
		}
	}

	if(mode == 1)
		target_cache = &m_cahce_priority;
	else
		target_cache = &m_cahce_regular;

	target_cache->push_front(block_adde);
}
